package com.ruoyi.management.statistical.carlocaltion.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.constant.TaxiConstant;
import com.ruoyi.management.basics.controller.BaseExtController;
import com.ruoyi.management.basics.service.ITCarService;
import com.ruoyi.management.rocketmq.TaxiMessage;
import com.ruoyi.management.statistical.carlocaltion.ro.GetCarAddressParam;
import com.ruoyi.management.statistical.carlocaltion.ro.GetDriverByCarNoParam;
import com.ruoyi.management.statistical.carlocaltion.service.ITCarLocationService;
import com.ruoyi.management.statistical.carlocaltion.vo.GetBigScreenVo;
import com.ruoyi.management.statistical.carlocaltion.vo.GetDriverByCarNoVo;
import com.ruoyi.management.warning.service.ITWarningService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 车辆位置采集信息Controller
 *
 * @author ruoyi
 * @date 2021-12-01
 */
@RestController
@RequestMapping("/location")
@Api(tags = "首页接口")
public class TCarLocationController extends BaseExtController {
    @Autowired
    private ITCarLocationService tCarLocationService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ITWarningService warningService;
    @Autowired
    private ITCarService carService;

    /**
     * 统计当日上线车辆数
     */
    @ApiOperation(value = " 统计当日上线车辆数", notes = "统计当日上线车辆数")
    @GetMapping(value = "/get_car_location")
    public AjaxResult getCarLocation() {
        //取redis
        Integer counts = 0;
        Long companyId = getCompanyId();
        if (null != companyId) {
            int company = companyId.intValue();
            String redisKey = CharSequenceUtil.format(TaxiConstant.ONLINE_CAR_REDIS_KEY, DateUtil.format(DateUtil.date(), "yyyyMMdd"), company);
            Object count = redisTemplate.opsForValue().get(redisKey);
            if (count != null) {
                counts = (Integer) count;
            }
            return AjaxResult.success(counts);
        } else {
            String allKey = CharSequenceUtil.format(TaxiConstant.ONLINE_CAR_REDIS_KEY_ALL, DateUtil.format(DateUtil.date(), "yyyyMMdd"));
            Object allObj = redisTemplate.opsForValue().get(allKey);
            if (allObj != null) {
                counts = (Integer) allObj;
            }
        }
        return AjaxResult.success(counts);
    }

    public static Set<String> scan(RedisTemplate<String, Object> redisTemplate, String pattern) {
        return redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
            Set<String> keysTmp = new HashSet<>();
            try (Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder()
                    .match(pattern)
                    .count(10000).build())) {
                while (cursor.hasNext()) {
                    keysTmp.add(new String(cursor.next(), "Utf-8"));
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return keysTmp;
        });
    }

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    public List<TaxiMessage> batchGet(Set<String> keyList) {
        /* 批量获取多条数据 */
        List<Object> objects = stringRedisTemplate.executePipelined(
                new RedisCallback<Object>() {
                    @Override
                    public Object doInRedis(RedisConnection connection) throws DataAccessException {
                        StringRedisConnection stringRedisConn = (StringRedisConnection) connection;
                        for (String key : keyList) {
                            stringRedisConn.get(key);
                        }
                        return null;
                    }
                });
        return objects.stream().map(val -> JSONUtil.toBean(String.valueOf(val), TaxiMessage.class)).collect(Collectors.toList());
    }

    @ApiOperation(value = "查询营运车辆数、重车数、空车数")
    @GetMapping("/get-cat-num")
    public AjaxResult getCatNum() {
        AjaxResult result = AjaxResult.success();
        Long companyId = getCompanyId();
        if(null == companyId){
            //空车数量
            Set<String> emptyKeys = redisTemplate.keys(CharSequenceUtil.format(TaxiConstant.EMPTY_NUM_CAR_KEY, DateUtil.format(DateUtil.date(), "yyyyMMdd"),"*"));
            List<Integer> emptyList = redisTemplate.opsForValue().multiGet(emptyKeys);
            Integer emptyNum = 0;
            if(!CollectionUtils.isEmpty(emptyList)){
                emptyNum = getSum(emptyList);
            }
            result.put("emptyNum",emptyNum);
            //重车数量
            Set<String> heavyKeys = redisTemplate.keys(CharSequenceUtil.format(TaxiConstant.HEAVY_NUM_CAR_KEY, DateUtil.format(DateUtil.date(), "yyyyMMdd"),"*"));
            List<Integer> heavyList = redisTemplate.opsForValue().multiGet(heavyKeys);
            Integer heavyNum = 0;
            if(!CollectionUtils.isEmpty(heavyList)){
                heavyNum = getSum(heavyList);
            }
            result.put("heavyNum",heavyNum);
            //营运数量
            Set<String> operateKeys = redisTemplate.keys(CharSequenceUtil.format(TaxiConstant.OPERATE_NUM_CAR_KEY,"*"));
            List<Integer> operateList = redisTemplate.opsForValue().multiGet(operateKeys);
            Integer operateNum = 0;
            if(!CollectionUtils.isEmpty(operateList)){
                operateNum = getSum(operateList);
            }
            result.put("offLineNum",operateNum - heavyNum - emptyNum);
        }else {
            //空车数量
            String emptyKey = CharSequenceUtil.format(TaxiConstant.EMPTY_NUM_CAR_KEY, DateUtil.format(DateUtil.date(), "yyyyMMdd"),companyId);
            Integer emptyNum = (Integer) redisTemplate.opsForValue().get(emptyKey);
            if(null == emptyNum){
                emptyNum = 0;
            }
            result.put("emptyNum",emptyNum);
            //重车数量
            String heavyKey = CharSequenceUtil.format(TaxiConstant.HEAVY_NUM_CAR_KEY, DateUtil.format(DateUtil.date(), "yyyyMMdd"),companyId);
            Integer heavyNum = (Integer) redisTemplate.opsForValue().get(heavyKey);
            if(null == heavyNum){
                heavyNum = 0;
            }
            result.put("heavyNum",heavyNum);
            //营运数量
            String operateKey = CharSequenceUtil.format( CharSequenceUtil.format(TaxiConstant.OPERATE_NUM_CAR_KEY,companyId));
            Integer operateNum = (Integer) redisTemplate.opsForValue().get(operateKey);
            if(null == operateNum){
                operateNum = 0;
            }
            result.put("offLineNum",operateNum - heavyNum -emptyNum);
        }
        return result;
    }

    public Integer getSum(List<Integer> list){
        Integer sum = 0;
        for (Integer integer : list) {
            sum += integer;
        }
        return sum;
    }
    @ApiOperation(value = "大屏实时数据(车辆位置)", notes = "大屏实时数据(车辆位置)")
    @GetMapping("/big-screen")
    public AjaxResult bigScreen() {
        Long companyId = getCompanyId();
        List<TaxiMessage> list;
        GetBigScreenVo vo = new GetBigScreenVo();
        if (null != companyId) {
            int company = companyId.intValue();
            Set<String> keys = scan(redisTemplate, CharSequenceUtil.format(TaxiConstant.REAL_TIME_PREFIX_REDIS_KEY_TODAY, company, "*", DateUtil.format(DateUtil.date(), "yyyyMMdd")));
            //Set<String> keys = redisTemplate.keys(CharSequenceUtil.format(TaxiConstant.REAL_TIME_PREFIX_REDIS_KEY_TODAY, company, "*", DateUtil.format(DateUtil.date(), "yyyyMMdd")));
            if (CollUtil.isEmpty(keys)) {
                return AjaxResult.success();
            }
            list = batchGet(keys);
            String warnKey = CharSequenceUtil.format(TaxiConstant.WARN_CAR_NUM, company);
            Object warnObj = redisTemplate.opsForValue().get(warnKey);
            if (Objects.nonNull(warnObj)) {
                vo.setWarnCarNum((Integer) warnObj);
            }
        } else {
            Set<String> allKeys = scan(redisTemplate, CharSequenceUtil.format(TaxiConstant.REAL_TIME_REDIS_KEY, "*", "*", "*", DateUtil.format(DateUtil.date(), "yyyyMMdd")));
            if (CollUtil.isEmpty(allKeys)) {
                return AjaxResult.success();
            }
            list = batchGet(allKeys);
            String warnAllKey = CharSequenceUtil.format(TaxiConstant.WARN_CAR_NUM_ALL);
            Object warnAllObj = redisTemplate.opsForValue().get(warnAllKey);
            if (Objects.nonNull(warnAllObj)) {
                vo.setWarnCarNum((Integer) warnAllObj);
            }
        }
        if (CollUtil.isEmpty(list)) {
            return AjaxResult.success();
        }
        Map<Integer, List<TaxiMessage>> groupByStatus = list.stream().collect(Collectors.groupingBy(TaxiMessage::getStatus));
        vo.setEmptyCarList(groupByStatus.get(1));
        vo.setHeavyCarList(groupByStatus.get(2));
        return AjaxResult.success(vo);
    }

    @ApiOperation(value = "根据车牌号获取所属公司和当前驾驶员")
    @GetMapping("/get-driver-by-carno")
    public AjaxResult getDriverByCarno(@Valid GetDriverByCarNoParam param) {
        GetDriverByCarNoVo vo = tCarLocationService.getDriverByCarno(param);
        return AjaxResult.success(vo);
    }

    @ApiOperation(value = "告警车辆信息")
    @GetMapping("/warning-car-list")
    public AjaxResult warningCarList() {
        return AjaxResult.success(warningService.warningCarList(getCompanyId()));
    }

    @ApiOperation(value = "告警车辆实时位置")
    @GetMapping("/warning-car-address")
    public AjaxResult warningCarAddress(@Valid GetCarAddressParam param) {
        return warningService.warningCarAddress(param);
    }

    private void onlineCar(Integer companyId) {
        String redisKey = CharSequenceUtil.format(TaxiConstant.ONLINE_CAR_REDIS_KEY, DateUtil.format(DateUtil.date(), "yyyyMMdd"), companyId);
        Object redisObj = redisTemplate.opsForValue().get(redisKey);
        if (Objects.isNull(redisObj)) {
            // 删除昨天的key
            String yesterdayKey = CharSequenceUtil.format(TaxiConstant.ONLINE_CAR_REDIS_KEY, DateUtil.format(DateUtil.yesterday(), "yyyyMMdd"), companyId);
            redisTemplate.delete(yesterdayKey);
        }
        redisTemplate.opsForValue().increment(redisKey, 1);
        //今日上线总数量
        String allKey = CharSequenceUtil.format(TaxiConstant.ONLINE_CAR_REDIS_KEY_ALL, DateUtil.format(DateUtil.date(), "yyyyMMdd"));
        Object allObj = redisTemplate.opsForValue().get(allKey);
        if (Objects.isNull(allObj)) {
            // 删除昨天的key
            String yesterdayKey = CharSequenceUtil.format(TaxiConstant.ONLINE_CAR_REDIS_KEY_ALL, DateUtil.format(DateUtil.yesterday(), "yyyyMMdd"));
            redisTemplate.delete(yesterdayKey);
        }
        redisTemplate.opsForValue().increment(allKey, 1);
    }

    @ApiOperation(value = "清除车牌号与公司对应关系")
    @GetMapping("/test1")
    public void test1(TaxiMessage message) {
        Set<String> keys = redisTemplate.keys(CharSequenceUtil.format(TaxiConstant.CAR_COMPANYID, "*"));
        redisTemplate.delete(keys);
    }

    @ApiOperation(value = "删除所有车辆位置信息")
    @GetMapping("/test4")
    public void test4(TaxiMessage message) {
        Set<String> allKeys = redisTemplate.keys(CharSequenceUtil.format(TaxiConstant.REAL_TIME_PREFIX_REDIS_KEY, "*"));
        redisTemplate.delete(allKeys);
    }

    @ApiOperation(value = "查询传入平台推送过来的车辆位置信息")
    @GetMapping("/test5")
    public AjaxResult test5(TaxiMessage message) {
        AjaxResult success = AjaxResult.success();
        String key = CharSequenceUtil.format(TaxiConstant.REAL_TIME_REDIS_KEY, "*", message.getPlatformId(), "*", DateUtil.format(DateUtil.date(), "yyyyMMdd"));
        Set<String> keys = redisTemplate.keys(key);
        List<TaxiMessage> list = redisTemplate.opsForValue().multiGet(keys);
        List<TaxiMessage> voList = new ArrayList<>();
        List<TaxiMessage> vos = new ArrayList<>();
        for (TaxiMessage vo : list) {
            if(vo.getCarNo().contains("桂桂")){
                voList.add(vo);
            }
            if(!vo.getCarNo().contains("桂")){
                vos.add(vo);
            }
        }
        success.put("桂桂", voList);
        success.put("不含桂", vos);
        success.put("vo", list);
        return success;
    }

    @ApiOperation(value = "根据车牌号查询车辆位置信息")
    @GetMapping("/test6")
    public AjaxResult test6(TaxiMessage message) {
        String key = CharSequenceUtil.format(TaxiConstant.REAL_TIME_REDIS_KEY, "*", "*", message.getCarNo(), "*");
        Set<String> keys = redisTemplate.keys(key);
        List<TaxiMessage> list = redisTemplate.opsForValue().multiGet(keys);
        return AjaxResult.success(list);
    }

    @ApiOperation(value = "查询车牌号与公司对不上的车牌号")
    @GetMapping("/test7")
    public AjaxResult test7(TaxiMessage message) {
        AjaxResult success = AjaxResult.success();
        String key = CharSequenceUtil.format(TaxiConstant.REAL_TIME_REDIS_KEY, null,"*", "*", "*");
        Set<String> keys = redisTemplate.keys(key);
        List<TaxiMessage> list = redisTemplate.opsForValue().multiGet(keys);
        List<String> carNoList = new ArrayList<>();
        for (TaxiMessage vo : list) {
            carNoList.add(vo.getCarNo());
        }
        success.put("a", carNoList);
        success.put("list", list);
        redisTemplate.delete(keys);
        return success;
    }
}
